home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1995…tember: Reference Library / Dev.CD Sep 95 RL / Dev.CD Sep 95 RL.toast / mac / Technical Documentation / develop / develop Issue 23 code / Documentary Synchronicity ƒ / Source ƒ / Support ƒ / EvenMoreFiles.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-06-10  |  11.0 KB  |  402 lines  |  [TEXT/KAHL]

  1. /* 4567890123456789012345678901234567890123456789012345678901234567 */
  2. #include <Errors.h>
  3. #include <Folders.h>
  4. #include <Devices.h>
  5. #include <TextUtils.h>
  6.  
  7. #include "EvenMoreFiles.h"
  8.  
  9. #include "Toolbox.h"
  10.  
  11. pascal OSErr GetFileSpec(short anFRefNum, FSSpec *aFileSpec) {
  12.     OSErr theError;
  13.     FCBPBRec pb;
  14.     Str255 theName;
  15.     short theVRefNum;
  16.     long theDirID;
  17.  
  18.     pb.ioRefNum = anFRefNum; /* the file to target */
  19.     pb.ioNamePtr = theName; /* return the name */
  20.     pb.ioFCBIndx = 0; /* not indexing */
  21.     pb.ioVRefNum = 0; /* all open files */
  22.     theError = PBGetFCBInfoSync(&pb);
  23.     if (theError == noErr) {
  24.         theDirID = pb.ioFCBParID;
  25.         theVRefNum = pb.ioFCBVRefNum;
  26.         theError = 
  27.             FSMakeFSSpec(theVRefNum, theDirID, theName, aFileSpec);
  28.     }
  29.     return theError;
  30. }
  31.  
  32. pascal OSErr GetVolumeModDate(short aVRefNum, unsigned long *aDate) {
  33.     OSErr theError = noErr;
  34.     HParamBlockRec pb;
  35.     
  36.     pb.volumeParam.ioVRefNum = aVRefNum; /* the target volume */
  37.     pb.volumeParam.ioVolIndex = 0; /* Use vRefNum */
  38.     pb.volumeParam.ioNamePtr = nil; /* Don't care about name */
  39.     theError = PBHGetVInfoSync(&pb);
  40.  
  41.     *aDate = pb.volumeParam.ioVLsMod;
  42.     return theError;
  43. }
  44.  
  45. pascal OSErr GetNameOfReferencedFile(short anFRefNum, Str255 aName) {
  46.     FCBPBRec pb;
  47.     OSErr theError = noErr;
  48.  
  49.     pb.ioRefNum = anFRefNum; /* the target file */
  50.     pb.ioNamePtr = aName; /* return the name */
  51.     pb.ioFCBIndx = 0; /* not indexing */
  52.     pb.ioVRefNum = 0; /* all open files */
  53.     theError = PBGetFCBInfoSync(&pb);
  54.     return theError;
  55. }
  56.  
  57. pascal OSErr GetFilesVolume(short anFRefNum, short *aVRefNum) {
  58.     FCBPBRec pb;
  59.     OSErr theError = noErr;
  60.  
  61.     pb.ioRefNum = anFRefNum; /* the target file */
  62.     pb.ioNamePtr = nil; /* do not care about file */
  63.     pb.ioFCBIndx = 0; /* not indexing */
  64.     pb.ioVRefNum = 0; /* all open files */
  65.     theError = PBGetFCBInfoSync(&pb);
  66.     if (theError == noErr) {
  67.         *aVRefNum = pb.ioFCBVRefNum;
  68.     }
  69.     return theError;
  70. }
  71.  
  72. pascal OSErr GetFileParID(short aRefNum, long *aParID) {
  73.     OSErr theError;
  74.     FCBPBRec pb;
  75.  
  76.     pb.ioRefNum = aRefNum; /* the target file */
  77.     pb.ioNamePtr = nil; /* do not care about name */
  78.     pb.ioFCBIndx = 0; /* not indexing */
  79.     pb.ioVRefNum = 0; /* all open files */
  80.     theError = PBGetFCBInfoSync(&pb);
  81.     if (theError == noErr) {
  82.         *aParID = pb.ioFCBParID;
  83.     }
  84.     return theError;
  85. }
  86.  
  87. pascal OSErr GetFolderParID(short aVRefNum, long aDirID, 
  88.         long *aParID) {
  89.     OSErr theError;
  90.     CInfoPBRec pb;
  91.  
  92.     pb.dirInfo.ioVRefNum = aVRefNum; /* the target volume */
  93.     pb.dirInfo.ioDrDirID = aDirID; /* the target directory */
  94.     pb.dirInfo.ioFDirIndex = -1; /* ioDrDirID specifies target */
  95.     pb.dirInfo.ioNamePtr = nil; /* do not care about name */
  96.     theError = PBGetCatInfoSync(&pb);
  97.     if (theError == noErr) {
  98.         *aParID = pb.dirInfo.ioDrParID;
  99.     }
  100.     return theError;
  101. }
  102.  
  103. pascal OSErr GetFolderName(short aVRefNum, long aDirID, Str255 aName) {
  104.     OSErr theError;
  105.     CInfoPBRec pb;
  106.  
  107.     pb.dirInfo.ioVRefNum = aVRefNum; /* the target volume */
  108.     pb.dirInfo.ioDrDirID = aDirID; /* the target directory */
  109.     pb.dirInfo.ioFDirIndex = -1; /* ioDrDirID specifies target */
  110.     pb.dirInfo.ioNamePtr = aName; /* do not care about name */
  111.     theError = PBGetCatInfoSync(&pb);
  112.     return theError;
  113. }
  114.  
  115. pascal OSErr GetVolumeName(short aVRefNum, Str255 aName) {
  116.     OSErr theError;
  117.     CInfoPBRec pb;
  118.  
  119.     pb.dirInfo.ioNamePtr = aName; /* return the name */
  120.     pb.dirInfo.ioVRefNum = aVRefNum; /* the target volume */
  121.     pb.dirInfo.ioDrDirID = fsRtDirID; /* volume name == root name */
  122.     pb.dirInfo.ioFDirIndex = -1; /* ioDrDirID specifies target */
  123.     theError = PBGetCatInfoSync(&pb);
  124.     return theError;
  125. }
  126.  
  127. pascal OSErr CanAccess(short aVRefNum, long aDirID, 
  128.         Boolean *canAccess) {
  129.     OSErr theError;
  130.     CInfoPBRec pb;
  131.  
  132.     pb.dirInfo.ioNamePtr = nil; /* don't care about name */
  133.     pb.dirInfo.ioVRefNum = aVRefNum;
  134.     pb.dirInfo.ioDrDirID = aDirID;
  135.     pb.dirInfo.ioFDirIndex = -1; /* ioDrDirID specifies target */
  136.     /*
  137.      * An obscure note in Inside Macintosh: Files on page 2-192 says,
  138.      * "The PBGetCatInfo function returns the directory access rights
  139.      * in the ioACUser field only for shared volumes. As a result, you
  140.      * should set this field to 0 before calling PBGetCatInfo."
  141.      *
  142.      * What this note really means is that PBGetCatInfo fills in the
  143.      * ioACUser field with the file access rights on shared volumes
  144.      * and does nothing with this field on non-shared volumes. There
  145.      * is a happy coincidence that on non-shared volumes you always
  146.      * have full access to all files. Furthermore, the ioACUser code
  147.      * for full access is zero (0).
  148.      *
  149.      * So... If you fill in the ioACUser field ahead of time with zero
  150.      * then after the call the field value will be correct EVEN if the
  151.      * file is not on a shared volume.
  152.      *
  153.      * IF YOU ARE WITH ME SO FAR...
  154.      *
  155.      * You may have noticed that attempting to set the ioACUser field
  156.      * of the DirInfo portion of a CInfoPBRec you will get a compile
  157.      * error. This is because this field was cleverly named 'filler2'.
  158.      *
  159.      * Thanks to Jim Luther for helping me through this bit of 
  160.      * cleverness--I don't think most developers get this kind of help!
  161.      */
  162.     pb.dirInfo.filler2 = 0; /* really is ioACUser field */
  163.     theError = PBGetCatInfoSync(&pb);
  164.     if (theError == noErr) {
  165.         pb.dirInfo.filler2 &= 0x7f; /* don't care if user is owner */
  166.         if (pb.dirInfo.filler2 == 0) { /* really is ioACUser field */
  167.                 *canAccess = true;
  168.         } else {
  169.                 *canAccess = false;
  170.         }
  171.     }
  172.     return theError;
  173. #if 0
  174.     /*
  175.      * This is the less clever way I was doing it originally which 
  176.      * required an additional line of code for the sake of clarity.
  177.      */
  178. #define kUserWrite 0x04000000L
  179. #define kUserRead 0x02000000L
  180.  
  181.     OSErr theError;
  182.     HParamBlockRec pb;
  183.     
  184.     pb.accessParam.ioNamePtr = nil; /* don't care about name */
  185.     pb.accessParam.ioVRefNum = aVRefNum;
  186.     pb.fileParam.ioDirID = aDirID;
  187.     theError = PBHGetDirAccessSync(&pb);
  188.     if (theError == noErr) {
  189.         Boolean noWriteAccess = 
  190.             ((pb.accessParam.ioACAccess & kUserWrite) == 0L);
  191.         Boolean noReadAccess = 
  192.             ((pb.accessParam.ioACAccess & kUserRead) == 0L);
  193.         
  194.         if (noWriteAccess || noReadAccess) {
  195.             *canAccess = false;
  196.         } else {
  197.             *canAccess = true;
  198.         }
  199.     } else if (theError == paramErr) {
  200.         /*
  201.          * Volume does not support directory access
  202.          */
  203.         *canAccess = true;
  204.         theError = noErr;
  205.     }
  206.     return theError;
  207. #endif
  208. }
  209.  
  210. pascal OSErr FileInTrashCan(short aFRefNum, Boolean *inTrash) {
  211.     OSErr theError;
  212.     short theVRefNum;
  213.     short theTrashVRefNum;
  214.     long theTrashDirID;
  215.     long theDirID;
  216.     
  217.     theError = GetVRefNum(aFRefNum, &theVRefNum);
  218.     if (theError == noErr) {
  219.         theError = FindFolder(theVRefNum, kTrashFolderType, false, 
  220.             &theTrashVRefNum, &theTrashDirID);
  221.         if (theError == fnfErr) {
  222.             theTrashDirID = 0;
  223.             theError = noErr;
  224.         }
  225.     }
  226.     if (theError == noErr) {
  227.         Boolean done = false;
  228.  
  229.         theError = GetFileParID(aFRefNum, &theDirID);
  230.         while ((!done) && (theError == noErr)) {
  231.             if (theDirID == theTrashDirID) {
  232.                 *inTrash = true;
  233.                 done = true;
  234.             } else if (theDirID == fsRtDirID) {
  235.                 *inTrash = false;
  236.                 done = true;
  237.             } else {
  238.                 theError = 
  239.                     GetFolderParID(theVRefNum, theDirID, &theDirID);
  240.             }
  241.         }
  242.         if (theError == afpAccessDenied) {
  243.             *inTrash = false;
  244.             theError = noErr;
  245.         }
  246.     } else {
  247.         if (theError == fnfErr) {
  248.             theError = noErr;
  249.             *inTrash = false;
  250.         }
  251.     }
  252.     return theError;
  253. }
  254.  
  255. pascal short GetFilesVolumeType(short aRefNum) {
  256.     DCtlHandle theDCtl;
  257.     StringPtr theDriverName;
  258.     short theType;
  259.     OSErr theError;
  260.     short theVRefNum;
  261.     HParamBlockRec pb;
  262.  
  263.     theError = GetVRefNum(aRefNum, &theVRefNum);
  264.     if (theError == noErr) {
  265.         pb.volumeParam.ioVolIndex = 0; /* use vRefNum */
  266.         pb.volumeParam.ioVRefNum = theVRefNum;
  267.         pb.volumeParam.ioNamePtr = nil; /* don't care about name */
  268.         theError = PBHGetVInfoSync(&pb);
  269.     }
  270.     if (theError == noErr) {
  271.         theDCtl = GetDCtlEntry(pb.volumeParam.ioVDRefNum);
  272.         if (((**theDCtl).dCtlFlags & (1L << 6)) == 1) { /* RAM or ROM */
  273.             /* RAM => dctlDriver is handle */
  274.             theDriverName = (StringPtr)*((Handle)(**theDCtl).dCtlDriver);
  275.        } else {
  276.             /* ROM => dctlDriver is pointer */
  277.             theDriverName = (StringPtr)(**theDCtl).dCtlDriver;
  278.         }
  279.         theDriverName += 18;
  280.         if (EqualString(theDriverName, "\p.Sony", true, true)) {
  281.             theType = GenericFloppy;
  282.         } else if (EqualString(theDriverName, "\p.AFPTranslator", true, 
  283.                 true)) {
  284.             theType = GenericServer;
  285.         } else if (EqualString(theDriverName, "\p.AppleCD", true, 
  286.                 true)) {
  287.             theType = GenericCDRom;
  288.         } else if (EqualString(theDriverName, "\p.EDisk", true, 
  289.                 true)) {
  290.             theType = GenericRAMDisk;
  291.         } else if (EqualString(theDriverName, "\p.SC/IOMEGA3.4", true, 
  292.                 true)) {
  293.             theType = IomegaBernoulliDisk;
  294.         } else {
  295.             theType = GenericHD;
  296.         }
  297.     } else {
  298.         theType = GenericHD;
  299.     }
  300.     return theType;
  301. }
  302.  
  303. pascal OSErr GetFilesVolumeStatus(short aRefNum, short *aStatus) {
  304.     OSErr theError;
  305.     short theVRefNum;
  306.     HParamBlockRec pb;
  307.  
  308.     theError = GetVRefNum(aRefNum, &theVRefNum);
  309.     if (theError == noErr) {
  310.         pb.volumeParam.ioVolIndex = 0; /* use vRefNum */
  311.         pb.volumeParam.ioVRefNum = theVRefNum;
  312.         pb.volumeParam.ioNamePtr = nil; /* don't care about name */
  313.         theError = PBHGetVInfoSync(&pb);
  314.     }
  315.     if (theError == noErr) {
  316.         if ((pb.volumeParam.ioVDrvInfo > 0) && 
  317.                 (pb.volumeParam.ioVDRefNum < 0)) {
  318.             *aStatus = online;
  319.         } else if ((pb.volumeParam.ioVDrvInfo == 0) && 
  320.                 (pb.volumeParam.ioVDRefNum < 0)) {
  321.             *aStatus = offline;
  322.         } else if ((pb.volumeParam.ioVDrvInfo == 0) && 
  323.                 (pb.volumeParam.ioVDRefNum > 0)) {
  324.             *aStatus = ejected;
  325.         } else {
  326.             *aStatus = online;
  327.         }
  328.     }
  329.     return theError;
  330. }
  331.  
  332. pascal OSErr GetFreeBytesOnVolume(short aVRefNum, 
  333.         unsigned long *aFreeBytes) {
  334.     OSErr theError = noErr;
  335.     ParamBlockRec pb;
  336.     
  337.     pb.volumeParam.ioNamePtr = nil; /* Don't care about name */
  338.     pb.volumeParam.ioVRefNum = aVRefNum;
  339.     pb.volumeParam.ioVolIndex = 0; /* Use vRefNum */
  340.     theError = PBGetVInfoSync(&pb);
  341.     if (theError == noErr) {
  342.         *aFreeBytes = 
  343.             pb.volumeParam.ioVFrBlk * pb.volumeParam.ioVAlBlkSiz;
  344.     }
  345.     return theError;
  346. }
  347.  
  348. pascal void FSGetFolderSize(FSSpecPtr aFolder, 
  349.         unsigned long *aFolderSize) {
  350.     *aFolderSize = 0L; /* Start with nothing */
  351.     (void)GetDirectorySize(aFolder->vRefNum, aFolder->parID, 
  352.         aFolderSize);
  353. }
  354.  
  355. pascal OSErr GetDirectorySize(long aVRefNum, short aDirID, 
  356.         unsigned long *aDirectorySize) {
  357.     static OSErr theError = noErr;
  358.     static CInfoPBRec pb;
  359.     short index = 1;
  360.  
  361. #define kRequiredStackSpace (36)
  362.      /* 36 bytes required on stack for each recursion */
  363.      if (StackSpace() < kRequiredStackSpace) 
  364.         return insufficientStackErr;
  365.  
  366.     do {
  367.         pb.dirInfo.ioDrDirID = aDirID;
  368.         pb.dirInfo.ioVRefNum = aVRefNum;
  369.         pb.dirInfo.ioNamePtr = nil;
  370.         pb.dirInfo.ioFDirIndex = index;
  371.         theError = PBGetCatInfoSync(&pb);
  372.         if (theError == noErr) {
  373.             if ((pb.dirInfo.ioFlAttrib & ioDirMask) != 0) { 
  374.                 /*
  375.                  * we have a directory -- recurse 
  376.                  */
  377.                 theError = GetDirectorySize(aVRefNum, 
  378.                     pb.dirInfo.ioDrDirID, aDirectorySize);
  379.                 if (theError == fnfErr) {
  380.                     theError = noErr; /* clear error on way back */
  381.                 }
  382.             } else { 
  383.                 /* 
  384.                  * we have a file -- add the physical length of it's forks 
  385.                  */
  386.                 *aDirectorySize += 
  387.                     (pb.hFileInfo.ioFlPyLen + pb.hFileInfo.ioFlRPyLen);
  388.             }
  389.         }
  390.         index++;
  391.    } while (theError == noErr);
  392.     return theError;
  393. }
  394.  
  395. pascal OSErr GetTrashFolder(short aVRefNum, FSSpecPtr aTrash) {
  396.     OSErr theError;
  397.     
  398.     theError = 
  399.         FindFolder(aVRefNum, kTrashFolderType, kDontCreateFolder, 
  400.         &(aTrash->vRefNum), &(aTrash->parID));
  401.     return theError;
  402. }